/* file: cg_node.cc */

#include "cg_node.h"

/**********************************
class:	CGNode
constructor
**********************************/
CGNode::CGNode()
{
    ip = "";
    level = 0;
    status = STAT_INIT;
}

CGNode::CGNode(string node_ip, int node_level)
{
    ip = node_ip;
    level = node_level;
    status = STAT_INIT;
    // image.initPosition(ip, level);

    hb_sec = HB_SEC;
    hb_timeout = HB_TIMEOUT;
    count_sec = 0;
}

/**********************************
class:	CGNode
method:	initCGNode
param:	node_ip, node_level
**********************************/
void
CGNode::initCGNode(string node_ip, int node_level, string root, int depth, char *str)
{
    ip = node_ip;
    level = node_level;
    image.initPosition(ip, level, root, depth);

    if (strlen(str) > 0)
    {
	image.buildCGImage(str, OFFLINE);
	image.setIpState(this->ip, ONLINE,image.getDepth());
#ifdef DEBUG
	printf("CGNode image at level %d\n", node_level);
	image.printCGTree();
#endif

	Set set;
	Set::size_type ix;

	image.indexChldNode(node_ip,node_level,&children);
	dispa.initRS();
	
	if (image.indexChldNode(node_ip, node_level, &set) > 0)
	{
	    for (ix = 0; ix != set.size(); ++ix)
	    {
		/* heartbeat */
		if (!hb_table.count(set[ix].ip))
		    hb_table[set[ix].ip] = 0;

		/* rs_list table */
		if (!rs_children.count(set[ix].ip))
		    rs_children[set[ix].ip] = 0;
	    }
	}
    }

    hb_sec = HB_SEC;
    hb_timeout = HB_TIMEOUT;
    count_sec = 0;

    status = STAT_INIT;		// enter STAT_INIT
}

/**********************************
class:	CGNode
method:	loadSubImage
param:	str
**********************************/
int
CGNode::loadSubImage(char *str)
{
    return image.buildCGImage(str, OFFLINE);
}

/**********************************
class:	CGNode
method:	indexChldNode
**********************************/
int
CGNode::indexChldNode(string cur_ip, int cur_level, Set *set)
{
    return this->image.indexChldNode(cur_ip, cur_level, set);
}

/**********************************
class:	CGNode
method:	registerCGNode()
**********************************/
void
CGNode::registerCGNode()
{
    char str[20];
    char filename[30], father[20];
    
    if (this->status != STAT_INIT) return;
    
    if (this->ip == this->image.getRoot())	// root_host, self registration
    {
	this->status = STAT_NORMAL;	// root to STAT_NORMAL
#ifdef RUN
	printf("Level %d at STAT_NORMAL\n", this->level);
#endif
	/* rs_list upload */
	if (this->level == getDepth()-1)
	{
	    fileToMap("source.txt");
	    getFather(father);
	    sendFile(father, "source.txt");
#ifdef DEBUG
	    printf("leaf send source up\n");
#endif
	}
	
	return;
    }
    sleep(1);
    Correspond init_c(TCP, RECV_PORT);
    init_c.setHead(this->ip, this->level, this->image.getRoot(), 0);
    sprintf(str, "%d\n", this->status);
    while (init_c.sendMessage(NODE_INIT, str) < 0)	// fail to send NODE_INIT, node to STAT_FAULT
	sleep(2);
    /* checking this node in root's image, then if get NODE_WORK, turn to STAT_NORMAL */
}

/**********************************
class:	CGNode
method:	recvMessage
param:	t - message type
	sender, s_level - sender's position
	str - message content
**********************************/
int
CGNode::recvMessage(MessageType t, string sender, int s_level, char *str)
{
    int s_stat;		// get sender's status from message_content
    string child;
    Position p;
    
    switch (t)
    {
	case NODE_INIT:		// only root receive it
	    if (this->level == 0)	// if root receive NODE_INIT from other nodes
	    {
		while (this->status != STAT_NORMAL);
		//printf("%d\n", image.getNodeState(sender));
		if (image.getNodeState(sender) == ONLINE)
		{
		    /* nodes init, send NODE_WORK back */
		    Correspond work_c(TCP, RECV_PORT);
		    work_c.setHead(this->ip, this->level, sender, s_level);
		    work_c.sendMessage(NODE_WORK, "");
#ifdef DEBUG1
		    printf("root send NODE_WORK to %s\n", sender.c_str());   
#endif
		}
		else
		{
		    /* node recover from fault */
		    this->status = STAT_ADJUST;
#ifdef RUN
		    printf("Level %d receive INIT from %s(%d), -> STAT_ADJUST\n", this->level, sender.c_str(), s_level);
#endif
		    p.ip = sender;
		    p.level = s_level;
		    Set set;
		    set.push_back(p);
		    do_adjust(set, ONLINE);
		}
		
	    }
	    break;
	    
	case NODE_WORK:		// only branch/leaf node receive it
	    //printf("%d %d\n", this->level, this->status);
	    if (this->level > 0)
	    {
		while (1) if (this->status == STAT_NORMAL || this->status == STAT_PAUSE) break;
		this->status = STAT_NORMAL;	// branch/leaf h node receive NODE_WORK, status to STAT_NORMAL
#ifdef RUN
		printf("Level %d receive WORK from %s(%d), -> STAT_NORMAL\n", this->level, sender.c_str(), s_level);
#endif
	    }
	    /*else if (this->level == 0)
	    {
		char str[BUFF_MAXSIZE];
		Correspond sendI(TCP, RECV_PORT);
		image.codeCGImage(this->ip, this->level, str);
		puts(str);
		sendI.setHead(this->ip, this->level, sender, -1);
		sendI.sendMessage(RECOVER_IMAGE, str);
	    }*/
	    break;

	case NODE_PAUSE:	// only branch/leaf node receive it
	    if (this->level > 0)
	    {
		while (this->status != STAT_NORMAL);
		this->status = STAT_PAUSE;
#ifdef RUN
		printf("Level %d receive PAUSE from %s(%d), -> STAT_PAUSE\n", this->level, sender.c_str(), s_level);
#endif
	    }
	    break;
	    
	case NODE_ADD:
	    while (this->status != STAT_NORMAL);
	    this->status = STAT_ADJUST;
#ifdef RUN
	    printf("Level %d receive N_ADD from %s(%d), -> STAT_ADJUST\n", this->level, sender.c_str(), s_level);
#endif
	    do_add(sender, str);
	    break;
	    
	case NODE_DEL:
	    while (this->status != STAT_NORMAL);
	    this->status = STAT_ADJUST;
#ifdef RUN
	    printf("Level %d receive N_DEL from %s(%d), -> STAT_ADJUST\n", this->level, sender.c_str(), s_level);
#endif
	    do_del(str);
	    break;
	    
	case RECOVER_ASKACK:		// only root receive it
	    sscanf(str, "%d", &s_stat);
	    if (s_stat == STAT_FAULT)
	    {
		this->status = STAT_ADJUST;
#ifdef RUN
		printf("Level %d receive ASKACK from recovered %s(%d), -> STAT_ADJUST\n", this->level, sender.c_str(), s_level);
#endif
		do_ack(sender, s_level);
	    }
	    break;
			
	case RECOVER_ACK:
	    if (this->status == STAT_FAULT)
	    {
		this->status = STAT_RECONSTRUCT;
#ifdef RUN
		printf("Level %d receive ACK from %s(%d), -> STAT_RECONSTRUCT\n", this->level, sender.c_str(), s_level);
#endif
		do_reconstruct(str);
	    }
	    break;

	case RECOVER_IMAGE:
	    while (this->status != STAT_NORMAL);
	    this->status = STAT_UPDATE;
#ifdef RUN
	    printf("Level %d receive IMAGE from %s(%d), -> STAT_UPDATE\n", this->level, sender.c_str(), s_level);
#endif
	    do_update(sender, s_level, str);	// update the image according to the receiverd_subimage
	    break;
	
	case RECOVER_RECONSTRUCT:
	    while (this->status != STAT_INIT && this->status != STAT_NORMAL && this->status != STAT_FAULT);
	    this->status = STAT_RECONSTRUCT;
#ifdef RUN
	    printf("Level %d receive RECONSTRUCT from %s(%d), -> STAT_RECONSTRUCT\n", this->level, sender.c_str(), s_level);
#endif
	    do_reconstruct(str);
	    break;

	case RECOVER_RECONFIG:
	    while (this->status != STAT_NORMAL);
	    this->status =STAT_RECONFIG;
#ifdef RUN
	    printf("Level %d receive RECONFIG from %s(%d), -> STAT_RECONFIG\n", this->level, sender.c_str(), s_level);
#endif
	    do_reconfig(sender);
	    break;
	    
	default: break;
    }
}

/**********************************
class:	CGNode
method:	recvHeartBeat
**********************************/
int
CGNode::recvHeartBeat(MessageType t, string child, char *str)
{
    /* rs_load information */
    strToMap(str);
    
    if (!hb_table.count(child))
    {
	/* child node recover from fault */
	while (this->status != STAT_NORMAL);
	this->status = STAT_ADJUST;
#ifdef RUN
	printf("Level %d get heartbeat from recovered %s, at STAT_ADJUST\n", this->level, child.c_str());
#endif

	int end_level;
	string off_ip;
	image.adjustImage(child, ONLINE, &end_level, &off_ip);
	image.indexChldNode(this->ip, this->level, &children);
	hb_table[child] = 0;
	
	if (this->level > 0)	// send newly_adjusted IMAGE to this father, except root
	{
	    Correspond sendI(TCP, RECV_PORT);
	    sendI.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	    image.codeCGImage(this->ip, this->level, str);
	    sendI.sendMessage(RECOVER_IMAGE, str);
#ifdef DEBUG
	    printf("Level %d send IMAGE to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
	}

#ifdef DEBUG
	this->image.printCGTree();
#endif
    
	this->status = STAT_NORMAL;
#ifdef RUN
	printf("Level %d at STAT_NORMAL\n", this->level);
#endif
    }
    else
    {
	hb_table[child] = 0;
    }
#ifdef DEBUG1
    printf("Level %d gets heartbeat from %s\n", this->level, child.c_str());
#endif
}

/**********************************
class:	CGNode
method:	checkTimeout
**********************************/
int
CGNode::checkTimeout()
{
    map<string, int>::iterator map_it;
    Position p;
    Set fault_set;

    /* only checkTimeout when STAT_NORMAL */
    if (this->status != STAT_NORMAL) return -1;
    
    for (map_it = hb_table.begin(); map_it != hb_table.end(); ++map_it)
    {
	if (++(map_it->second) > hb_timeout)
	{
#ifdef RUN
	    printf("! Level %d lose heartbeat from %s\n", this->level, map_it->first.c_str());
#endif
	    p.ip = map_it->first;
	    p.level = this->level+1;
	    fault_set.push_back(p);
	}
    }
    if (fault_set.size() != 0)	// lose some heartbeat
    {
	/* ask root whether it is online */
	if (this->ip != this->image.getRoot())
	{
	    Correspond ask_ack(TCP, RECV_PORT);
	    ask_ack.setHead(this->ip, this->level, this->image.getRoot(), 0);
	    char str[20];
	    sprintf(str, "%d\n", this->status);
	    if (ask_ack.sendMessage(RECOVER_ASKACK, str) < 0)	// fail to send ASK_ACK, node to STAT_FAULT
	    {
		this->status = STAT_FAULT;
#ifdef RUN
		printf("Level %d -> STAT_FAULT\n", this->level);
#endif
		/* continue to send ASK_ACK to root */
		sprintf(str, "%d\n", this->status);
		while (ask_ack.sendMessage(RECOVER_ASKACK, str) < 0);
		return 0;
	    }
	}
	
	this->status = STAT_ADJUST;
#ifdef RUN
	printf("Level %d -> STAT_ADJUST\n", this->level);
#endif
	do_adjust(fault_set, OFFLINE);		// update the image
    }
    return 0;
}

/**********************************
class:	CGNode
method:	sendHeartBeat
**********************************/
int
CGNode::sendHeartBeat(int load)
{
    char str[BUFF_MAXSIZE];
    
    if (this->level == 0) return 0;	// root, not sending heartbeat
    if ((++count_sec) < hb_sec) return 0;	// not hb_sec time
    count_sec = 0;
    if (this->status == STAT_NORMAL)
    {
    	Correspond send_hb(UDP, HB_PORT);
    	send_hb.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
    	//sprintf(str, "%d\n", this->status);
	if (this->level == getDepth()-1)
	{
	    setLoad(load);
	    mapToStr(str);
	}
	else
	{
	    mapToStr(str);
	}
    	if (send_hb.sendMessage(HEART_BEAT, str) < 0)
    	{
	    printf("fail to send heartbeat\n");
	    return -1;
    	}
#ifdef DEBUG1
    	printf("Level %d sends heartbeat to %s\n", this->level, this->image.getFather().c_str());
#endif
    }
    return 0;
}

/**********************************
class:	CGNode
method:	do_ack
if a child recover from STAT_FAULT, 
**********************************/
int
CGNode::do_ack(string sender, int s_level)
{
    Correspond send_c(TCP, RECV_PORT);
    char str[BUFF_MAXSIZE];
    int end_level;
    string off_ip;

#ifdef DEBUG
    printf("CGNode::do_ack()\n");
#endif

    if (image.adjustImage(sender, ONLINE, &end_level, &off_ip) != sender)
	printf("do_ack error\n");
    if (end_level != s_level) printf("do_ack error\n");
    
    send_c.setHead(this->ip, this->level, sender, s_level);
    send_c.sendMessage(RECOVER_ACK, str);
#ifdef DEBUG
	printf("Level %d send ACK to %s(%d)\n", this->level, sender.c_str(), s_level);
#endif

    if (this->level > 0)	// not root
    {
	image.codeCGImage(this->ip, this->level, str);
	send_c.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	send_c.sendMessage(RECOVER_IMAGE, str);
#ifdef DEBUG
	printf("Level %d send IMAGE to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
    }
   
    hb_table[sender] = 0;	// update the heartbeat_table
    hb_table.erase(off_ip);
    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}

/**********************************
class:	CGNode
method:	do_adjust
param:	set - position set
	stat - ONLINE or OFFLINE
adjust the image, delete the offline_node
then send RECOVER_IMAGE to father level by level
**********************************/
int
CGNode::do_adjust(Set set, CGNodeStatus stat)
{
    vector<Position>::size_type ix;
    Correspond rect(TCP, RECV_PORT);
    string child, off_ip;
    int end_level;
    char str[BUFF_MAXSIZE];
    struct in_addr naddr;

#ifdef DEBUG
    printf("CGNode::do_adjust()\n");
#endif
    
    if (this->status != STAT_ADJUST) return -1;
    for (ix = 0; ix < set.size(); ++ix)
    {
	if ((child = image.adjustImage(set[ix].ip, stat, &end_level, &off_ip)) != "")
	{
	    rect.setHead(this->ip, this->level, child, end_level);
	    image.codeCGImage(child, end_level, str);
	    //puts(str);
	    //if (rect.sendMessage(RECOVER_RECONSTRUCT, str) < 0)
	    rect.sendMessage(RECOVER_RECONSTRUCT, str);
#ifdef DEBUG
	    printf("Level %d send RECONSTRUCT to %s(%d)\n", this->level, child.c_str(), end_level);
#endif
	    
	    /* update the heartbeat_table */
	    if (end_level == this->level+1)
		hb_table[child] = 0;
	}

	/* update the heartbeat_table */
	if (off_ip != "")
	{
	    hb_table.erase(off_ip);
    
	    /* change resource list */
	    dispa.deleteNode(off_ip);
	    removeRSList(off_ip);
	}
    }

    if (stat == OFFLINE)
    {
	/* delete rs_list with fault IP */
	for (ix = 0; ix < set.size(); ++ix)
	{
	    dispa.deleteNode(set[ix].ip);
	    removeRSList(set[ix].ip);
	}
    }

    /* update its children's set */
    children.clear();
    image.indexChldNode(this->ip, this->level, &children);
    
    //if (this->image.getFather() != "0.0.0.0")
    if (this->level > 0)
    {
	Correspond send_c(TCP, RECV_PORT);
	send_c.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	if (stat == ONLINE)
	{
	    image.codeCGImage(this->ip, this->level, str);
	    send_c.sendMessage(RECOVER_IMAGE, str);
#ifdef DEBUG
	    printf("Level %d send IMAGE to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
	}
	else if (stat == OFFLINE)
	{
	    for (ix = 0; ix < set.size(); ++ix)
	    {
		/* change resource list */
		dispa.deleteNode(set[ix].ip.c_str());
		removeRSList(set[ix].ip.c_str());
		
		inet_aton(set[ix].ip.c_str(), &naddr);
		sprintf(str, "%u", naddr);
		send_c.sendMessage(NODE_DEL, str);
	    }
#ifdef DEBUG
	    printf("Level %d send N_DEL to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
	}
    }
    
#ifdef RUN
    this->image.printCGTree();
#endif

    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}

/**********************************
class:	CGNode
method:	do_update
update the image, according to the received subimage
then send new image to its father
**********************************/
int
CGNode::do_update(string child, int s_level, char *s_str)
{
    Correspond sendI(TCP, RECV_PORT);
    char str[BUFF_MAXSIZE];
    Set set;

#ifdef DEBUG
    printf("CGNode::do_update()\n");
#endif
    
    image.updateImage(child, s_level, s_str);
    image.indexChldNode(this->ip, this->level, &children);
    image.indexChldNode(child, s_level, &set);
    for (Set::size_type ix = 0; ix != set.size(); ++ix)
    {
	if (hb_table.count(set[ix].ip))
	{
	    hb_table.erase(set[ix].ip);
	}
    }

    if (!hb_table.count(child))
	hb_table[child] = 0;
    
    if (this->level > 0)
    {
	image.codeCGImage(this->ip, this->level, str);
	sendI.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	sendI.sendMessage(RECOVER_IMAGE, str);
#ifdef DEBUG
	printf("Level %d send IMAGE to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
    }

#ifdef RUN
    this->image.printCGTree();
#endif

    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}

/**********************************
class:	CGNode
method:	do_reconstruct
**********************************/
int
CGNode::do_reconstruct(char *s_str)
{
    Correspond send_c(TCP, RECV_PORT);
    Set set;
    char str[BUFF_MAXSIZE], father[20];
    vector<Position>::size_type ix;
    struct in_addr naddr;
    
#ifdef DEBUG
    printf("CGNode::do_reconstruct()\n");
#endif
    
    /* reconstruct image */
    image.buildCGImage(s_str, ONLINE);
    /* reconstruct RSList */
    reconstructRSList();

    image.indexChldNode(this->ip, this->level, &set);
    children.clear();
    children = set;
    hb_table.clear();
    for (ix = 0; ix != set.size(); ++ix)
    {
	/* send adjusting message with sub_image to children */
	if (set[ix].ip == this->ip)
	{
	    image.codeCGImage(set[ix].ip, set[ix].level, str);
	    send_c.setHead(this->ip, this->level, set[ix].ip, set[ix].level);
	    send_c.sendMessage(RECOVER_RECONSTRUCT, str);
#ifdef DEBUG
	    printf("Level %d send RECONSTRUCT to %s(%d)\n", this->level, set[ix].ip.c_str(), set[ix].level);
#endif
	}
	else
	{
	    inet_aton(this->ip.c_str(), &naddr);
	    sprintf(str, "%u ", naddr);
	    send_c.setHead(this->ip, this->level, set[ix].ip, set[ix].level);
	    send_c.sendMessage(RECOVER_RECONFIG, str);
#ifdef DEBUG
	    printf("Level %d send RECONFIG to %s(%d)\n", this->level, set[ix].ip.c_str(), set[ix].level);
#endif
	}

	/* update the heartbeat_table */
	hb_table[set[ix].ip] = 0;
    }

    if (this->level > 1 && this->image.getFather() != this->ip)
    {
	send_c.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	send_c.sendMessage(RECOVER_IMAGE, s_str);
#ifdef DEBUG
	printf("Level %d send IAMGE to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
    }

    if (this->level == getDepth()-1)
    {
	fileToMap("source.txt");
	getFather(father);
	sendFile(father, "source.txt");
#ifdef DEBUG
	printf("leaf send source up\n");
#endif
    }

#ifdef RUN
    this->image.printCGTree();
#endif

    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}

/**********************************
class:	CGNode
method:	do_reconfig
**********************************/
int
CGNode::do_reconfig(string father)
{
    char filename[30];

    this->image.setFather(father);

    /* send its rs_list to father */
    sprintf(filename, "%s__%d", this->ip.c_str(), this->level);
    mapToFile(filename);
    sendFile(father.c_str(), filename);
#ifdef DEBUG
    printf("Level %d send its rs_list to %s\n", this->level, father.c_str());
#endif
    
    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}

/**********************************
class:	CGNode
method:	do_add
**********************************/
int
CGNode::do_add(string sender, char *s_str)
{
    Correspond send_c(TCP, RECV_PORT);
    struct in_addr nadd;

#ifdef DEBUG
    printf("CGNode::do_add()\n");
#endif

}

/**********************************
class:	CGNode
method:	do_del
**********************************/
int
CGNode::do_del(char *s_str)
{
    struct in_addr naddr;
    char s[20];
    int end_level;
    string off_ip;
    
#ifdef DEBUG
    printf("CGNode::do_del()\n");
#endif
    sscanf(s_str, "%u", &naddr);
    sprintf(s, "%s", inet_ntoa(naddr));

    /* adjust its image, to remove the offline node */
    image.adjustImage(s, OFFLINE, &end_level, &off_ip);
    image.indexChldNode(this->ip, this->level, &children);
    
    /* change resource list */
    dispa.deleteNode(s);
    removeRSList(s);
    
    if (this->level > 0)
    {
	Correspond send_del(TCP, RECV_PORT);
	send_del.setHead(this->ip, this->level, this->image.getFather(), this->level-1);
	send_del.sendMessage(NODE_DEL, s_str);
#ifdef DEBUG
	printf("Level %d send N_DEL to %s(%d)\n", this->level, this->image.getFather().c_str(), this->level-1);
#endif
    }

#ifdef RUN
    this->image.printCGTree();
#endif

    this->status = STAT_NORMAL;
#ifdef RUN
    printf("Level %d at STAT_NORMAL\n", this->level);
#endif
}


/***********************************************************
used for resource dispatching
***********************************************************/

/**********************************
class:	CGNode
method:	match_ip
**********************************/
int
CGNode::match_ip(char *ip)
{
    return dispa.match_ip(seg_ip, ip);
}

int
CGNode::findFit(char *filename, char *ip)
{
    return dispa.findFit(filename, ip);
}

int
CGNode::has_source(char *filename)
{
    return dispa.has_source(filename);
}

int
CGNode::sendFile(const char *ip, char *file)
{
        FILE* fp;
        int sockfd;
        char buf[4096];
        struct sockaddr_in servaddr;
        int n = 0;

        if((fp = fopen(file,"rb")) < 0){
                printf("open file failed in CGNode sendFile\n");
                return -1;
        }
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
                printf("socket() error in CGNode sendFile\n");
                return -1;
        }
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(FILE_PORT);
        if (inet_pton(AF_INET, ip, &servaddr.sin_addr) < 0){
                printf("inet_pton() error in CGNode sendFile\n");
                return -1;
        }
        if (connect(sockfd, (sockaddr *)&servaddr, sizeof(servaddr)) < 0){
                printf("connect() error in CGNode sendFile\n");
                return -1;
        }

        while((n = fread(buf,1,sizeof(buf),fp))>0){
                if((n = send(sockfd, buf, n, 0)) < 0){
                        printf("send() error ");
                        return -1;
                }
        }
		
        close(sockfd);
        fclose(fp);
#ifdef DEBUG
	printf("Level %d sendFile to %s\n", this->level, ip);
#endif
        return 0;
}

int CGNode::listenFile(){
        int listenfd;
        struct sockaddr_in servaddr;

        if((listenfd = socket(AF_INET,SOCK_STREAM,0)) < 0){
                printf("socket() error in in CGNode listenFile\n");
                return -1;
        }
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(FILE_PORT);
        if((bind(listenfd,(sockaddr*)&servaddr,sizeof(servaddr))) < 0){
                printf("bind() error in CGNode listenFile\n");
                return -1;
        }
        listen(listenfd,LISTENQ);
	return listenfd;
}

int CGNode::recvFile(char *filename, string sender)
{
    while (this->status != STAT_NORMAL);
#ifdef DEBUG
    printf("%s(%d) receive rs_list from %s\n", this->ip.c_str(), this->level, sender.c_str());
#endif
    fileToMap(filename);
    addRSList(sender);
    return 0;
}

int
CGNode::addRSList(string child)
{
    map<string, int>::iterator map_it;
    char filename[30];
    string father;
    
    /*if (!rs_children.count(child))
    {
#ifdef DEBUG
	printf("Level %d: child not exist in rs_list\n", this->level);
#endif
	return -1;
    }*/
    /*if (rs_children[child] != 0)
    {
#ifdef DEBUG
	printf("already get rs_list\n");
#endif
	return -1;
    }*/
    rs_children[child] = 1;

    map_it = rs_children.begin();
    while (map_it != rs_children.end())
    {
	if (map_it->second == 0) break;
	++map_it;
    }
    if (map_it == rs_children.end())
    {
	/* collect rs_list complete */
#ifdef DEBUG
	printf("Level %d collect rs_list complete\n", this->level);
#endif
	if (this->level > 0)
	{
	    sprintf(filename, "%s__%d", this->ip.c_str(), this->level);
	    mapToFile(filename);
	    father = getFather();
	    sendFile(father.c_str(), filename);
	}
	else
	{
	    /* root collect all rs_list from the whole tree */
	    mapToFile("debug");
	}
    }
    return 0;
}

int CGNode::removeRSList(string child)
{
    if (rs_children.count(child))
	rs_children.erase(child);
    
    if (this->level == 0)
	mapToFile("debug1");
    
    return 0;
}

int CGNode::updateRSList(string child)
{
    return 0;
}

int CGNode::reconstructRSList()
{
    Set set;
    vector<Position>::size_type ix;
    
    rs_children.clear();
    indexChldNode(this->ip, this->level, &set);
    for (ix = 0; ix != set.size(); ++ix)
	rs_children[set[ix].ip] = 0;
    return 0;
}

int CGNode::sendFirstChild(char* str){
	vector<Position>::iterator iter;
	char req_ip[20];
	char filename[30];
	char tmp[60];	
	Correspond send(TCP,RSMESS_PORT);
	
	sscanf(str,"%s %s",req_ip,filename);
	iter = children.begin();
	send.setHead(ip,level,(*iter).ip,(*iter).level);
	if(send.sendMessage(FORWARD_REQ,str) < 0)
		return -1;
	sprintf(tmp,"%s_%s%c",req_ip,filename,'\0');
	childptr[tmp] = iter;
	return 0;
}

int CGNode::sendNextChild(char* str){
	char req_ip[20];
	char filename[30];
	char tmp[60];
	Correspond send(TCP,RSMESS_PORT);

	sscanf(str,"%s %s",req_ip,filename);
	sprintf(tmp,"%s_%s%c",req_ip,filename,'\0');
	childptr[tmp]++;
	if(childptr[tmp] == children.end())
		return -1;
	else{
		send.setHead(ip,level,(*childptr[tmp]).ip,level+1);
		send.sendMessage(FORWARD_REQ,str);
#ifdef DEBUG
		printf("Level %d send FORWARD_REQ to %s\n", this->level, (*childptr[tmp]).ip.c_str());
#endif
	}
	return 0;
}

void CGNode::erase(char* str){
	char req_ip[20];
	char filename[30];
	char tmp[60];

	sscanf(str,"%s %s",req_ip,filename);
	sprintf(tmp,"%s_%s%c",req_ip,filename,'\0');
	childptr.erase(tmp);
}

void CGNode::sendSuccess(char* str){
	char father[20];
	Correspond send(TCP,RSMESS_PORT);

	getFather(father);
	send.setHead(ip,level,father,level-1);
	send.sendMessage(FIND_SUCCESS,str);
}

void CGNode::sendFail(char* str){
        char father[20];
        Correspond send(TCP,RSMESS_PORT);

        getFather(father);
        send.setHead(ip,level,father,level-1);
        send.sendMessage(FIND_FAIL,str);
}

